package com.bookstore.utils;

import com.bookstore.entity.Book;
import com.bookstore.service.BookService;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * 协同过滤类
 */
public class CFUtils {
    public static Long getUser(Map<Long,Map<String,Double>> prefs,Long userId){
        //目标用户
        Map<String,Double> user = prefs.get(userId);
        System.out.println("用户是："+userId+"获取评论："+user.get("605147b5f1f745c39b337c402abde340"));
        //相似系数比
        Map<Long, Double> simUserSimMap = new HashMap<Long, Double>();
        System.out.println("皮尔逊相关系数:");
        for (Map.Entry<Long, Map<String, Double>> userPerfEn : prefs.entrySet()) {
            Long userIds = userPerfEn.getKey();
            if (!userId.equals(userIds)) {
                double sim = getUserSimilar(user, userPerfEn.getValue());
                System.out.println(userId+"与" + userIds + "之间的相关系数:" + sim);
                simUserSimMap.put(userIds, sim);
            }
        }

        return CFUtils.backUser(simUserSimMap);
    }

    public static Long backUser(Map<Long, Double> simUserSimMap){
        Double sim = -1.0;
        Long user = null;
        for (Map.Entry<Long, Double> simUser:simUserSimMap.entrySet()){
            if(sim<=simUser.getValue()) {
                sim = simUser.getValue();
                user = simUser.getKey();
        }
        }
        return user;
    }

    //Claculate Pearson Correlation Coefficient
    public static double getUserSimilar(Map<String, Double> pm1, Map<String, Double> pm2) {
        int n = 0;// 数量n
        Double sxy = 0.0;// Σxy=x1*y1+x2*y2+....xn*yn
        Double sx = 0.0;// Σx=x1+x2+....xn
        Double sy = 0.0;// Σy=y1+y2+...yn
        Double sx2 = 0.0;// Σx2=(x1)2+(x2)2+....(xn)2
        Double sy2 = 0.0;// Σy2=(y1)2+(y2)2+....(yn)2
        for (Map.Entry<String, Double> pme : pm1.entrySet()) {
            String key = pme.getKey();
            Double x = pme.getValue();
            Double y = pm2.get(key);
            if (x != null && y != null) {
                n++;
                sxy += x * y;
                sx += x;
                sy += y;
                sx2 += Math.pow(x, 2);
                sy2 += Math.pow(y, 2);
            }
        }
        // p=(Σxy-Σx*Σy/n)/Math.sqrt((Σx2-(Σx)2/n)(Σy2-(Σy)2/n));
        double sd = sxy - sx * sy / n;
        double sm = Math.sqrt((sx2 - Math.pow(sx, 2) / n) * (sy2 - Math.pow(sy, 2) / n));
        if (sd==0.0 && sm == 0.0){
            return -1;
        }
        return Math.abs(sm == 0 ? 1 : sd / sm);
    }

}
